package cn.kbyue.retrydemo.service.impl;

import cn.kbyue.retrydemo.service.RetryService;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;

import java.time.LocalTime;

@Service
public class RetryServiceImpl implements RetryService {

    /**
     * value：抛出指定异常才会重试
     * include：和value一样，默认为空，当exclude也为空时，默认所有异常
     * exclude：指定不处理的异常
     * maxAttempts：最大重试次数，默认3次
     * backoff：重试等待策略，
     * 默认使用@Backoff，@Backoff的value默认为1000L，我们设置为2000； 以毫秒为单位的延迟（默认 1000）
     * multiplier（指定延迟倍数）默认为0，表示固定暂停1秒后进行重试，如果把multiplier设置为1.5，则第一次重试为2秒，第二次为3秒，第三次为4.5秒。
     *
     * @param code 请求参数
     * @return
     * @throws Exception
     */
    @Override
    @Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 2000, multiplier = 1.5), listeners = {"defaultRetryListener"})
    public int testRetry(int code) throws Exception {
        System.out.println("testRetry() 被调用,时间：" + LocalTime.now());
        if (code == 0) {
            throw new Exception("参数错误！");
        }
        System.out.println("testRetry() 被调用, 跳过异常！");
        return 200;
    }

    /**
     * 用于@Retryable重试失败后处理方法。
     * 注意事项：
     * 方法的返回值必须与@Retryable方法一致
     * 方法的第一个参数，必须是Throwable类型的，建议是与@Retryable配置的异常一致，其他的参数，需要哪个参数，写进去就可以了（@Recover方法中有的）
     * 该回调方法与重试方法写在同一个实现类里面
     *
     * 如果不写, 则重试完毕后抛出异常.
     */
    @Recover
    public int testRetryRecover(Exception e, int code) {
        System.out.println("重试失败回调方法执行！！！！");
        //记日志到数据库 或者调用其余的方法
        System.out.println("异常信息:" + e.getMessage());
        return 400;
    }

}
